#include<iostream>
#include<string>
#include <unistd.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>
const std::string path = "/home/fang/fang/test15";//路径
int projid = 0x6666;//用户定义的数字

//操作系统，申请空间，是按照块为单位的 : 4KB,1KB,2KB,4MB
int shmsize = 4097;

mode_t mode = 0600;
//手动写一个转16进制代码
std::string tohex(key_t k)
{
    char buff[shmsize];
    snprintf(buff,sizeof(buff),"0x%x",k);//把k转换成16进制，方便查看
    return buff;
}


struct data
{
    char status[32];//数据状态
    char lasttime[48];//消息最新被修改的数据
    char imge[1024];//发送图片的图片大小
};

class commshm
{
private:
    void creatshm(int ipcshm)//创建共享内存
    {
            //通过ftok形成唯一值-key
            _k = ::ftok(path.c_str(),projid);
            if(_k < 0)
            {
                std::cerr << "创建key失败" << std::endl;
                return;
            }
    
            //创建共享内存并且获取
            //注意:共享内存也有权限
            _shmid = ::shmget(_k,shmsize, ipcshm);
            if(_shmid < 0)
            {
                std::cerr << "创建共享内存失败" << std::endl;
                return;
            }
            std::cout << "shmid:" << _shmid << std::endl;
    }
public:
    commshm()
    :_shmid(-1)
    ,_k(0)
    ,_ret(nullptr)
    {}
    void cjshm()//创建共享内存
    {
        if(_shmid == -1)
            creatshm(IPC_CREAT | IPC_EXCL | mode);
    }
    void getshm()//共享内存，只想获取
    {
        //只想获取，单独使用IPC_CREAT
            creatshm(IPC_CREAT);
    }
    void attshm()//挂接
    {
        //共享内存挂接到自己的虚拟地址空间
        _ret = shmat(_shmid,nullptr,0);
        if((long long)_ret == -1)
        {
            std::cout << "挂接失败" << std::endl;
            return;
        }
        std::cout << "挂接成功" << std::endl;
        //void*在 64 位系统中通常是 8 字节，所以不能要4字节的int,用long long
        //std::cout << "已挂接到虚拟地址空间:"<< (long long)ret << std::endl;
    }

    void dateshm()//去关联
    {
        if(_ret != nullptr)
            ::shmdt(_ret);
    }
    void deleshm()//删除共享内存
    {
        //删除共享内存
        shmctl(_shmid,IPC_RMID,nullptr);
        
    }
    //返回共享内存映射到虚拟地址的，起始地址
    void* getaddr()
    {
        return _ret;
    }


    void shmmete()//显示共享内存的信息
    {

    }
    ~commshm()
    {}
private:
    int _shmid;
    key_t _k;
    void* _ret;
};

commshm shm;